<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>Events and Signals in PyQt4</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="PyQt, PyQt4, events, signals, tutorial, Python, Linux">
<meta name="description" content="In this part of the PyQt4 tutorial, we 
work with events and signals.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href=".." title="Home">Contents</a>


<h1>Events and Signals in PyQt4</h1>

<p>
In this part of the PyQt4 programming tutorial, we will 
explore events and singnals occuring in applications.
</p>

<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* NewSquare */
google_ad_slot = "0364418177";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 

<h2>Events</h2>

<p>
Events are an important part in any GUI program. Events are generated by users or by the system. 
When we call the application's <code>exec_()</code> method, the application enters the main loop.
The main loop fetches events and sends them to 
the objects. 
Trolltech has introduced a unique signal and slot mechanism.
</p>

<p> 
Events are an important part in any GUI program.
All GUI applications are event-driven. An application reacts to different event 
types which are generated during its life. Events are generated mainly by the 
user of an application. But they can be generated by other means as well. e.g. 
internet connection, window manager, timer.
In the event model, there are three participants:
</p> 
 
 
<ul> 
<li>event source</li> 
<li>event object</li> 
<li>event target</li> 
</ul> 
 
<p> 
The <b>event source</b> is the object whose state changes. It generates Events. 
The <b>event object</b> (Event) encapsulates the state changes in the event source.
The <b>event target</b> is the object that wants to be notified. Event source object 
delegates the task of handling an event to the event target. 
</p> 
 
<p> 
When we call the application's <code>exec_()</code> method, the application
enters the main loop. The main loop fetches events and sends them to the objects. 
Signals and slots are used for communication between objects. A <b>signal</b> 
is emitted when a particular event occurs. A <b>slot</b> can be any Python callable.
A slot is called when a signal connected to it is emitted.
</p> 


<h2>New API</h2>

<p>
PyQt4.5 introduced a new style API for working with signals and slots. 
</p>

<pre>
QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), self.onClicked)
</pre>

<p>
This is the old style API. 
</p>

<pre>
button.clicked.connect(self.onClicked)
</pre>

<p>
The new style adheres more to the Python standards. 
</p>




<h2>Signals &amp; Slots</h2>

<p>
This is a simple example, demonstrating signals and slots in PyQt4.
</p>


<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
ZetCode PyQt4 tutorial 

In this example, we connect a signal
of a QtGui.QSlider to a slot 
of a QtGui.QLCDNumber. 

author: Jan Bodnar
website: zetcode.com 
last edited: October 2011
"""

import sys
from PyQt4 import QtGui, QtCore


class Example(QtGui.QWidget):
    
    def __init__(self):
        super(Example, self).__init__()
        
        self.initUI()
        
    def initUI(self):
        
        lcd = QtGui.QLCDNumber(self)
        sld = QtGui.QSlider(QtCore.Qt.Horizontal, self)

        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(lcd)
        vbox.addWidget(sld)

        self.setLayout(vbox)
        sld.valueChanged.connect(lcd.display)
        
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Signal &amp; slot')
        self.show()
        
def main():
    
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
</pre>

<p>
In our example, we display a <code>QtGui.QLCDNumber</code>
and a <code>QtGui.QSlider</code>. We change the lcd number by dragging the slider
knob. 
</p>

<pre class="explanation">
sld.valueChanged.connect(lcd.display)
</pre>

<p>
Here we connect a <code>valueChanged</code> signal of the slider to the
<code>display</code> slot of the lcd number.
</p>

<p>
The <b>sender</b> is an object that sends a signal. The <b>receiver</b> is the object, 
that receives the signal. The <b>slot</b> is the method, that reacts to the signal.
</p>


<br>
<img src="/img/gui/pyqt4/sigslot.png" alt="Signals &amp; slot">
<div class="figure">Figure: Signal &amp; slot</div>


<h2>Reimplementing event handler</h2>


<p>
Events in PyQt4 are processed often by reimplementing event handlers.
</p>


<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
ZetCode PyQt4 tutorial 

In this example, we reimplement an 
event handler. 

author: Jan Bodnar
website: zetcode.com 
last edited: October 2011
"""

import sys
from PyQt4 import QtGui, QtCore


class Example(QtGui.QWidget):
    
    def __init__(self):
        super(Example, self).__init__()
        
        self.initUI()
        
    def initUI(self):      
        
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Event handler')
        self.show()
        
    def keyPressEvent(self, e):
        
        if e.key() == QtCore.Qt.Key_Escape:
            self.close()
        
def main():
    
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
</pre>

<p>
In our example, we reimplement the <code>keyPressEvent()</code> event handler.
</p>

<pre class="explanation">
def keyPressEvent(self, e):
    
    if e.key() == QtCore.Qt.Key_Escape:
        self.close()
</pre>

<p>
If we click the escape button, the application terminates.
</p>


<h2>Event sender</h2>

<p>
Sometimes it is convenient to know, which widget is the 
sender of a signal. For this, PyQt4 has a <code>sender()</code>
method.
</p>


<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
ZetCode PyQt4 tutorial 

In this example, we determine the event sender
object.

author: Jan Bodnar
website: zetcode.com 
last edited: October 2011
"""

import sys
from PyQt4 import QtGui, QtCore


class Example(QtGui.QMainWindow):
    
    def __init__(self):
        super(Example, self).__init__()
        
        self.initUI()
        
    def initUI(self):      

        btn1 = QtGui.QPushButton("Button 1", self)
        btn1.move(30, 50)

        btn2 = QtGui.QPushButton("Button 2", self)
        btn2.move(150, 50)
      
        btn1.clicked.connect(self.buttonClicked)            
        btn2.clicked.connect(self.buttonClicked)
        
        self.statusBar()
        
        self.setGeometry(300, 300, 290, 150)
        self.setWindowTitle('Event sender')
        self.show()
        
    def buttonClicked(self):
      
        sender = self.sender()
        self.statusBar().showMessage(sender.text() + ' was pressed')
        
def main():
    
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
</pre>

<p>
We have two buttons in our example. In the buttonClicked() method
we determine, which button we have clicked by calling the <code>sender()</code>
method.
</p>

<pre class="explanation">
btn1.clicked.connect(self.buttonClicked)            
btn2.clicked.connect(self.buttonClicked)
</pre>

<p>
Both buttons are connected to the same slot. 
</p>

<pre class="explanation">
def buttonClicked(self):
  
    sender = self.sender()
    self.statusBar().showMessage(sender.text() + ' was pressed')
</pre>

<p>
We detemine the signal source by calling the <code>sender()</code> method.
In the statusbar of the application, we show the label 
of the button being pressed.
</p>


<br>
<img src="/img/gui/pyqt4/eventsender.png" alt="Event sender">
<div class="figure">Figure: Event sender</div>


<h2>Emitting signals</h2>

<p>
Objects created from <code>QtCore.QObject</code> can emit signals. 
If we click on the button, a <code>clicked()</code> signal is generated. In the 
following example we will see, how we can emit signals.
</p>

<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
ZetCode PyQt4 tutorial 

In this example, we show how to emit a
custom signal. 

author: Jan Bodnar
website: zetcode.com 
last edited: October 2011
"""

import sys
from PyQt4 import QtGui, QtCore


class Communicate(QtCore.QObject):
    
    closeApp = QtCore.pyqtSignal() 
    

class Example(QtGui.QMainWindow):
    
    def __init__(self):
        super(Example, self).__init__()
        
        self.initUI()
        
    def initUI(self):      

        self.c = Communicate()
        self.c.closeApp.connect(self.close)       
        
        self.setGeometry(300, 300, 290, 150)
        self.setWindowTitle('Emit signal')
        self.show()
        
    def mousePressEvent(self, event):
        
        self.c.closeApp.emit()
        
def main():
    
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

</pre>

<p>
We create a new signal called <code>closeApp</code>. This signal is 
emitted, during a mouse press event. The signal is connected to the
<code>close()</code> slot of the <code>QtGui.QMainWindow</code>.
</p>

<pre class="explanation">
class Communicate(QtCore.QObject):
    
    closeApp = QtCore.pyqtSignal() 
</pre>

<p>
We create a class based on a <code>QtCore.QObject</code>. 
It creates a closeApp signal when instantiated. 
</p>

<pre class="explanation">
self.c = Communicate()
self.c.closeApp.connect(self.close)     
</pre>

<p>
An instance of the Communicate class is created. We connect
a <code>close()</code> slot of the <code>QtGui.QMainWindow</code>
to the closeApp signal. 
</p>

<pre class="explanation">
def mousePressEvent(self, event):
    
    self.c.closeApp.emit()
</pre>

<p>
When we click on the window with a mouse pointer, 
the <code>closeApp</code> signal is emitted. 
</p>

<hr class="btm">

<p>
In this part of the PyQt4 tutorial, we have covered signals and slots. 
</p>

<br>
<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div>
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified October 10, 2011  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

